%{
	StringBuilder buffer = null;
%}

%namespace Infinity.Parser.Syntax

%using Infinity.Parser.Lexical

%scanbasetype LexicalParser
%parsertype SyntaxParser
%partial

%start start
%visibility public
%tokentype Token

%token PROCEDURE
%token OPERATOR

%token PREFIX
%token INFIX
%token POSTFIX
%token ITERATIVE

%token BEGIN
%token END
%token RETURN
%token IF
%token THEN
%token ELSE
%token ELSEIF
%token WHILE
%token FOR
%token FOREACH
%token DO
%token IN
%token OUT
%token TO
%token BY
%token VAR

%token ASSIGNMENT
%token END_COMMAND
%token COMMA_SEPARATOR
%token COLON

%token LEFT_REGULAR_PARENTHESES
%token RIGHT_REGULAR_PARENTHESES
%token LEFT_SQUARE_PARENTHESES
%token RIGHT_SQUARE_PARENTHESES
%token LEFT_CURLY_PARENTHESES
%token RIGHT_CURLY_PARENTHESES
%token LEFT_POINTY_PARENTHESES
%token RIGHT_POINTY_PARENTHESES

%token PRECONDITION
%token POSTCONDITION

%token OPERATOR_COMMAND
%token NUMERIC_OPERATOR
%token LOGICAL_OPERATOR

%token NUMBER
%token STRING
%token BOOLEAN

%token IDENTIFIER

%type <_ExpressionType> expression

%union
{
	public Type _ExpressionType;
	public string _Value;
}

%%

start  		:  
			   {
					Console.WriteLine("start -> epsilon");
			   }
		|
			   functions_statement 
               { 
					Console.WriteLine("start -> functions_statement");
               }
		;
functions_statement	: function
					  {
						  Console.WriteLine("functions_statement -> function");
					  }
|
					  function functions_statement
					  {
						  Console.WriteLine("functions_statement -> function functions_statement");
					  }
		;

function	:	conditions PROCEDURE IDENTIFIER LEFT_REGULAR_PARENTHESES arguments RIGHT_REGULAR_PARENTHESES 
					declarations
				BEGIN 
					command_statement 
				END END_COMMAND
				{
					Console.WriteLine("function -> PROCEDURE IDENTIFIER LEFT_REGULAR_PARENTHESES arguments RIGHT_REGULAR_PARENTHESES BEGIN command_statement END END_COMMAND");
				}
		;

declarations	:	
					{
						Console.WriteLine("declarations -> epsilon");
					}
;

arguments	:	IDENTIFIER
				{
					Console.WriteLine("arguments -> IDENTIFIER");
				}
|
				IDENTIFIER COMMA_SEPARATOR arguments
				{
					Console.WriteLine("arguments -> IDENTIFIER COMMA_SEPARATOR arguments");
				}
;

command_statement	: 
					{
						Console.WriteLine("command_statement -> epsilon");
					}
|
					conditions END_COMMAND
					{	
						Console.WriteLine("command_statement -> conditions END_COMMAND");
					}
|
					conditions if_statement END_COMMAND command_statement
					{
						Console.WriteLine("command_statement -> conditions if_statement END_COMMAND command_statement");
					}
|
					conditions while_statement END_COMMAND command_statement
					{
						Console.WriteLine("command_statement -> conditions while_statement END_COMMAND command_statement");
					}
|
					conditions for_statement END_COMMAND command_statement
					{
						Console.WriteLine("for_statement -> conditions  for_statement END_COMMAND command_statement");
					}
|
					conditions foreach_statement END_COMMAND command_statement
					{
						Console.WriteLine("foreach_statement -> conditions foreach_statement END_COMMAND command_statement");
					}
|
					conditions assignment END_COMMAND command_statement
					{
						Console.WriteLine("command_statement -> conditions assignment END_COMMAND command_statement");
					};

assignment	:	IDENTIFIER ASSIGNMENT expression
				{
					Console.WriteLine("IDENTIFIER ASSIGNMENT expression");
				};

if_statement	:	IF expression THEN command_statement else_if_statement END
					{
						Console.WriteLine("if_statement -> IF expression THEN command_statement else_if_statement END");
					}
|
					IF expression THEN command_statement else_if_statement ELSE command_statement END
					{
						Console.WriteLine("if_statement -> IF expression THEN command_statement else_if_statement ELSE command_statement END");
					};

else_if_statement	:	
						{
							Console.WriteLine("else_if_statement -> epsilon");
						}
|
						ELSEIF expression THEN command_statement
						{
							Console.WriteLine("else_if_statement -> ELSE IF expression THEN command_statement");
						};

while_statement	:	WHILE expression DO command_statement END
					{
						Console.WriteLine("while_statement -> WHILE expression DO command_statement END");
					};

for_statement	:	FOR IDENTIFIER ASSIGNMENT expression TO expression DO command_statement END
					{
						Console.WriteLine("for_statement -> for IDENTIFIER ASSIGNMENT expression TO expression DO command_statement END");
					}
|
					FOR IDENTIFIER ASSIGNMENT expression TO expression BY expression DO command_statement END
					{
						Console.WriteLine("for IDENTIFIER ASSIGNMENT expression TO expression BY expression DO command_statement END");
					};

foreach_statement	:	FOREACH IDENTIFIER IN expression DO command_statement END
					{
						Console.WriteLine("foreach_statement -> foreach IDENTIFIER IN expression DO command_statement END");
					};

conditions		:	
					{
						Console.WriteLine("conditions -> epsilon");
					}
|
					precondition
					{
						Console.WriteLine("conditions -> precondition");
					}
|
					postcondition
					{
						Console.WriteLine("conditions -> postcondition");
					}
|
					precondition postcondition
					{
						Console.WriteLine("conditions -> precondition postcondition");
					}
|
					postcondition precondition
					{
						Console.WriteLine("conditions -> postcondition precondition");
					};

precondition	:	
					LEFT_SQUARE_PARENTHESES PRECONDITION expression RIGHT_SQUARE_PARENTHESES
					{
						Console.WriteLine("precondition -> LEFT_SQUARE_PARENTHESES 'Q' COLON expression RIGHT_SQUARE_PARENTHESES");
					};

postcondition	:	
					LEFT_SQUARE_PARENTHESES POSTCONDITION expression RIGHT_SQUARE_PARENTHESES
					{
						Console.WriteLine("precondition -> LEFT_SQUARE_PARENTHESES 'R' COLON expression RIGHT_SQUARE_PARENTHESES");
					};

expression	:	constant
				{
					Console.WriteLine("expression -> constant");
				}
|
				LEFT_REGULAR_PARENTHESES expression RIGHT_REGULAR_PARENTHESES
				{
					Console.WriteLine("expression -> LEFT_REGULAR_PARENTHESES expression RIGHT_REGULAR_PARENTHESES");
				}
|
				expression operator expression
				{
					Console.WriteLine("expression -> expression operator expression");
				}
;

operator	:	NUMERIC_OPERATOR
				{
					Console.WriteLine("operator -> NUMERIC_OPERATOR {0}", yytext);
				}
|
				LOGICAL_OPERATOR
				{
					Console.WriteLine("operator -> LOGICAL_OPERATOR {0}", yytext);
				}
|	
				OPERATOR_COMMAND
				{
					Console.WriteLine("operator -> OPERATOR_COMMAND {0}", yytext);
				}
;
constant	:	STRING
				{
					Console.WriteLine("constant -> STRING");
				}
|
				BOOLEAN
				{
					Console.WriteLine("constant -> BOOLEAN");
				}
|
				NUMBER
				{
					Console.WriteLine("constant -> NUMBER");
				};

%%

	public SyntaxParser(LexicalParser scanner) : base(scanner) {}